#include <stdio.h>
#include <stdint.h>

#include "nuclei_sdk_soc.h"
#include "riscv_math.h"
#include "ref_mean.h"

#define ARRAY_SIZE 138

float32_t f32_array[] = {
    94.118553,  91.433388, -2.924870,  60.056095,  -71.622734, -15.647743,
    83.147102,  58.441467, 91.898483,  31.148140,  -92.857666, 69.825859,
    86.798653,  35.747032, 51.548027,  48.626495,  -21.554596, 31.095577,
    -65.762665, 41.209217, -93.633430, -44.615402, -90.765724, 0,
    94.118553,  91.433388, -2.924870,  60.056095,  -71.622734, -15.647743,
    83.147102,  58.441467, 91.898483,  31.148140,  -92.857666, 69.825859,
    86.798653,  35.747032, 51.548027,  48.626495,  -21.554596, 31.095577,
    -65.762665, 41.209217, -93.633430, -44.615402, -90.765724, 0,
    94.118553,  91.433388, -2.924870,  60.056095,  -71.622734, -15.647743,
    83.147102,  58.441467, 91.898483,  31.148140,  -92.857666, 69.825859,
    86.798653,  35.747032, 51.548027,  48.626495,  -21.554596, 31.095577,
    -65.762665, 41.209217, -93.633430, -44.615402, -90.765724, 0,
    94.118553,  91.433388, -2.924870,  60.056095,  -71.622734, -15.647743,
    83.147102,  58.441467, 91.898483,  31.148140,  -92.857666, 69.825859,
    86.798653,  35.747032, 51.548027,  48.626495,  -21.554596, 31.095577,
    -65.762665, 41.209217, -93.633430, -44.615402, -90.765724, 0,
    94.118553,  91.433388, -2.924870,  60.056095,  -71.622734, -15.647743,
    83.147102,  58.441467, 91.898483,  31.148140,  -92.857666, 69.825859,
    86.798653,  35.747032, 51.548027,  48.626495,  -21.554596, 31.095577,
    -65.762665, 41.209217, -93.633430, -44.615402, -90.765724, 0,
    94.118553,  91.433388, -2.924870,  60.056095,  -71.622734, -15.647743,
    83.147102,  58.441467, 91.898483,  31.148140,  -92.857666, 69.825859,
    86.798653,  35.747032, 51.548027,  48.626495,  -21.554596, 31.095577,
    -65.762665, 41.209217, -93.633430, -44.615402, -90.765724, 0};

q7_t q7_array[] = {-104, 82, 49, -47, 115, -120, -16, -31, 67,  75, -81, -3,
                   -14,  37, 53, 65,  -58, 46,   39,  -87, -98, -1, 117, 0,
                   -104, 82, 49, -47, 115, -120, -16, -31, 67,  75, -81, -3,
                   -14,  37, 53, 65,  -58, 46,   39,  -87, -98, -1, 117, 0,
                   -104, 82, 49, -47, 115, -120, -16, -31, 67,  75, -81, -3,
                   -14,  37, 53, 65,  -58, 46,   39,  -87, -98, -1, 117, 0,
                   -104, 82, 49, -47, 115, -120, -16, -31, 67,  75, -81, -3,
                   -14,  37, 53, 65,  -58, 46,   39,  -87, -98, -1, 117, 0,
                   -104, 82, 49, -47, 115, -120, -16, -31, 67,  75, -81, -3,
                   -14,  37, 53, 65,  -58, 46,   39,  -87, -98, -1, 117, 0,
                   -104, 82, 49, -47, 115, -120, -16, -31, 67,  75, -81, -3,
                   -14,  37, 53, 65,  -58, 46,   39,  -87, -98, -1, 117, 0};

q15_t q15_array[] = {
    -41, 21,  -71, 64,  -63, 1,   50,  100, 117, 12,  -93, -90, -63, 87,  -63,
    80,  -66, 109, -39, -78, -64, 29,  -7,  0,   -41, 21,  -71, 64,  -63, 1,
    50,  100, 117, 12,  -93, -90, -63, 87,  -63, 80,  -66, 109, -39, -78, -64,
    29,  -7,  0,   -41, 21,  -71, 64,  -63, 1,   50,  100, 117, 12,  -93, -90,
    -63, 87,  -63, 80,  -66, 109, -39, -78, -64, 29,  -7,  0,   -41, 21,  -71,
    64,  -63, 1,   50,  100, 117, 12,  -93, -90, -63, 87,  -63, 80,  -66, 109,
    -39, -78, -64, 29,  -7,  0,   -41, 21,  -71, 64,  -63, 1,   50,  100, 117,
    12,  -93, -90, -63, 87,  -63, 80,  -66, 109, -39, -78, -64, 29,  -7,  0,
    -41, 21,  -71, 64,  -63, 1,   50,  100, 117, 12,  -93, -90, -63, 87,  -63,
    80,  -66, 109, -39, -78, -64, 29,  -7,  0};

q31_t q31_array[] = {
    -9722,  21681,  5587,   3258,   27341,  -14036, 16855,  16628,  -7836,
    4444,   -27797, -29233, 2018,   18295,  28443,  -24255, 4510,   -2007,
    -31988, -10675, -22140, 19286,  -12373, 0,      -9722,  21681,  5587,
    3258,   27341,  -14036, 16855,  16628,  -7836,  4444,   -27797, -29233,
    2018,   18295,  28443,  -24255, 4510,   -2007,  -31988, -10675, -22140,
    19286,  -12373, 0,      -9722,  21681,  5587,   3258,   27341,  -14036,
    16855,  16628,  -7836,  4444,   -27797, -29233, 2018,   18295,  28443,
    -24255, 4510,   -2007,  -31988, -10675, -22140, 19286,  -12373, 0,
    -9722,  21681,  5587,   3258,   27341,  -14036, 16855,  16628,  -7836,
    4444,   -27797, -29233, 2018,   18295,  28443,  -24255, 4510,   -2007,
    -31988, -10675, -22140, 19286,  -12373, 0,      -9722,  21681,  5587,
    3258,   27341,  -14036, 16855,  16628,  -7836,  4444,   -27797, -29233,
    2018,   18295,  28443,  -24255, 4510,   -2007,  -31988, -10675, -22140,
    19286,  -12373, 0,      -9722,  21681,  5587,   3258,   27341,  -14036,
    16855,  16628,  -7836,  4444,   -27797, -29233, 2018,   18295,  28443,
    -24255, 4510,   -2007,  -31988, -10675, -22140, 19286,  -12373, 0};

float32_t f32_out;
q31_t q31_out;
q15_t q15_out;
q7_t q7_out;

float32_t f32_out_ref;
q31_t q31_out_ref;
q15_t q15_out_ref;
q7_t q7_out_ref;

static uint64_t enter_cycle;
static uint64_t exit_cycle;
static uint64_t start_cycle;
static uint64_t end_cycle;
static uint64_t cycle;

#define BENCH_INIT()            enter_cycle=__get_rv_cycle(); \
                                printf("CSV, BENCH START, %u\n", (uint32_t)enter_cycle);
#define BENCH_START(func)       start_cycle=__get_rv_cycle();
#define BENCH_END(func)         end_cycle=__get_rv_cycle(); \
                                cycle=end_cycle-start_cycle; \
                                printf("CSV, %s, %u\n", #func, (uint32_t)cycle);
#define BENCH_FINISH()          exit_cycle=__get_rv_cycle(); \
                                cycle=exit_cycle-enter_cycle; \
                                printf("CSV, BENCH END, %u\n", (uint32_t)cycle);

void f32_mean_compare()
{
    BENCH_START(riscv_mean_f32);
    riscv_mean_f32(f32_array, ARRAY_SIZE, &f32_out);
    BENCH_END(riscv_mean_f32);

    BENCH_START(ref_mean_f32);
    ref_mean_f32(f32_array, ARRAY_SIZE, &f32_out_ref);
    BENCH_END(ref_mean_f32);

    printf("riscv vs ref: %f, %f\n", f32_out, f32_out_ref);
}

void q7_mean_compare()
{
    BENCH_START(riscv_mean_q7);
    riscv_mean_q7(q7_array, ARRAY_SIZE, &q7_out);
    BENCH_END(riscv_mean_q7);

    BENCH_START(ref_mean_q7);
    ref_mean_q7(q7_array, ARRAY_SIZE, &q7_out_ref);
    BENCH_END(ref_mean_q7);

    printf("riscv vs ref: %d, %d\n", q7_out, q7_out_ref);

}

void q15_mean_compare()
{
    BENCH_START(riscv_mean_q15);
    riscv_mean_q15(q15_array, ARRAY_SIZE, &q15_out);
    BENCH_END(riscv_mean_q15);

    BENCH_START(ref_mean_q15);
    ref_mean_q15(q15_array, ARRAY_SIZE, &q15_out_ref);
    BENCH_END(ref_mean_q15);

    printf("riscv vs ref: %d, %d\n", q15_out, q15_out_ref);
}

void q31_mean_compare()
{
    BENCH_START(riscv_mean_q31);
    riscv_mean_q31(q31_array, ARRAY_SIZE, &q31_out);
    BENCH_END(riscv_mean_q31);

    BENCH_START(ref_mean_q31);
    ref_mean_q31(q31_array, ARRAY_SIZE, &q31_out_ref);
    BENCH_END(ref_mean_q31);

    printf("riscv vs ref: %d, %d\n", q31_out, q31_out_ref);
}

int main(void)
{
    BENCH_INIT();
    f32_mean_compare();
    q7_mean_compare();
    q15_mean_compare();
    q31_mean_compare();
    BENCH_FINISH();

    return 0;
}
